#include <dirent.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
    if (argc == 2) {                    // 如果有两个参数，表示要杀死指定进程
        int pid = atoi(argv[1]);        // 获取进程号
        if (kill(pid, SIGTERM) == 0) {  // 终止指定进程
            printf("进程 %d 终止成功\n", pid);
        } else {  // 终止进程失败
            perror("终止进程失败");
        }
    } else if (argc == 1) {           // 如果只有一个参数，表示要列出所有进程
        DIR* dir = opendir("/proc");  // 打开/proc目录
        if (dir) {
            struct dirent* entry;  // 目录项结构
            printf("进程号-进程名字\n");
            while ((entry = readdir(dir)) != NULL) {  // 遍历目录中的每个项
                // 检查是否是一个目录
                if (entry->d_type == DT_DIR) {
                    // 检查一个字符串是否只包含数字字符，如果是一般则时进程号
                    if (strspn(entry->d_name, "0123456789") == strlen(entry->d_name)) {
                        int pid = atoi(entry->d_name);  // 获取进程号
                        printf("%d  ", pid);            // 打印进程号

                        char comm_path[256];  // 存储进程名字文件的路径
                        snprintf(comm_path, sizeof(comm_path), "/proc/%s/comm", entry->d_name);
                        FILE* comm_file = fopen(comm_path, "r");  // 打开进程名字文件
                        if (comm_file) {
                            char name[256];                              // 存储进程名字
                            if (fgets(name, sizeof(name), comm_file)) {  // 从文件中读取名字
                                printf("%s", name);
                            }
                            fclose(comm_file);
                        }
                    }
                }
            }
            closedir(dir);
        }
    } else {  // 如果输入两个或者以上参数，则表示输出此函数的功能
        printf("此函数的用法：\n");
        printf("当用户输入一个参数时：打印系统当前所有进程 ./program\n");
        printf("当用户输入两个参数时：杀死指定进程 ./program <进程号>\n");
        printf("当用户输入三个及以上参数时：输出此函数的功能 ./program <1> <2>\n");
    }
    return 0;
}
